/******************************************************************************
 *                                                                            *
 *               (c) 2008-2009 HutLab. All rights reserved.                   *
 *                        Eduardo Henrique Leite                              *
 *                                                                            *
 ******************************************************************************

 History:
 Created 01/01/2009
 Added methods Contains and Remove 05/01/2009

 */

package hutlab.sudoku.engine.base;

/**
 * Dynamic array helper class.
 */
public class ArrayList {

    // ----- FIELDS -----

    private Object[] mItems;
    private int mCount;

    // ----- GETTERS -----

    /**
     * Returns number of items in the current list.
     */
    public int getCount(){
        return mCount;
    }

    // ----- CONSTRUCTOR -----
    
    /**
     * Creates a new ArrayList object.
     */
    public ArrayList() {
        this.mCount = 0;
        this.mItems = new Object[10];
    }

    // ----- PUBLIC -----

    /**
     * Adds an object to the list.
     */
    public void add(Object item) {
        if (item != null){
            if (this.mCount >= mItems.length){
                adjustSize();
            }
            this.mItems[mCount] = item;
            this.mCount++;
        }
    }

    /**
     * Clears the list items.
     */
    public void clear(){
        for (int i=0; i<this.mCount; i++){
            this.mItems[i] = null;
        }
        
        this.mCount = 0;
    }

    /**
     * Converts list to array.
     */
    public Object[] toArray(){
        Object[] result = new Object[this.mCount];
        System.arraycopy(this.mItems, 0, result, 0, this.mCount);
        return result;
    }

    /**
     * Gets object at given position.
     */
    public Object getElement(int index){
        if (index < 0 || index > this.mCount){
            return null;
        }
        else {
            return this.mItems[index];
        }
    }

    public boolean contains(Object element) {
        if (element == null) {
            return false;
        }
        for (int i = 0; i < this.mCount; i++) {
            Object object = this.mItems[i];
            if (object.equals(element)) {
                return true;
            }
        }
        return false;
    }

    public Object remove( int index ) {
        if (index < 0 || index >= this.mCount ) {
            return null;
        }
        Object removed = this.mItems[ index ];
        for (int i = index+1; i < this.mCount; i++) {
            this.mItems[ i-1 ] = this.mItems[ i ];
        }
        this.mCount--;
        this.mItems[ this.mCount ] = null;
        return removed;
    }

    public boolean remove( Object element ) {
        if (element == null) {
            return false;
        }
        int index = -1;
        for (int i = 0; i < this.mCount; i++) {
            Object object = this.mItems[i];
            if ( object.equals( element ) ) {
                index = i;
                break;
            }
        }
        if (index == -1) {
            return false;
        }
        for (int i = index+1; i < this.mCount; i++) {
            this.mItems[ i-1 ] = this.mItems[ i ];
        }
        this.mCount--;
        this.mItems[ this.mCount ] = null;
        return true;
    }

    // ----- PRIVATE -----

    // Adjusts the array size.
    private void adjustSize(){
        int capacity = this.mItems.length + 10;
        Object[] newArray = new Object[capacity];
        System.arraycopy(this.mItems, 0, newArray, 0, this.mCount);
        this.mItems = newArray;
    }
}
